package jwt

import (
	"errors"
	"time"

	ojwt "github.com/dgrijalva/jwt-go"
)

var TokenError = errors.New("the token is invalid")
var ExpiredToken = errors.New("the token expired")

type JwtConfig struct {
	Secret string `json:"secret"`
	// 过期时间
	Expire int64 `json:"expire"`
	// 刷新时间
	RefreshExpire int64 `json:"reflesh_expire"`
}
type JwtUserData struct {
	Username string `json:"username"`
	ID       int64  `json:"id"`
}
type JwtResponse struct {
	Token        string
	RefleshToken string
}

type UserData struct {
	Username string `json:"username"`
	ID       int64  `json:"id"`
}

func (jc *JwtConfig) Gernate(userData UserData) (JwtResponse, error) {
	token := ojwt.New(ojwt.SigningMethodHS256)

	claims := token.Claims.(ojwt.MapClaims)
	claims["username"] = userData.Username
	claims["user_id"] = userData.ID
	claims["exp"] = time.Now().Add(time.Hour * time.Duration(jc.Expire)).Unix()
	claims["iat"] = time.Now().Unix()
	claims["type"] = "token"

	gertoken, err := token.SignedString([]byte(jc.Secret))
	if err != nil {
		return JwtResponse{}, err
	}
	claims["type"] = "reflesh"
	refleshtoken, err := token.SignedString([]byte(jc.Secret))
	if err != nil {
		return JwtResponse{}, err
	}
	return JwtResponse{
		Token:        gertoken,
		RefleshToken: refleshtoken,
	}, nil
}

func (jc *JwtConfig) Parse(tokenStr string) (*JwtUserData, bool, error) {

	token, er := ojwt.Parse(tokenStr, func(token *ojwt.Token) (interface{}, error) {
		return []byte(jc.Secret), nil
	})
	if er != nil {
		return nil, false, TokenError
	}
	if claims, ok := token.Claims.(ojwt.MapClaims); ok && token.Valid {
		user := &JwtUserData{
			Username: claims["username"].(string),
			ID:       int64(claims["user_id"].(float64)),
		}
		return user, claims["type"].(string) == "reflesh", nil
	} else {
		return nil, false, ExpiredToken
	}

}
